﻿using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Gmantis.Controls
{
    [TemplatePart(Name = "Line", Type = typeof(Shape))]
    public class TreeViewLine : Control
    {
        // Fields
        internal Shape _elementLine;
        internal bool _isLoaded;
        private bool _throwStrokeDashArrayChanged = true;
        internal const string LineElementName = "Line";
        public static readonly DependencyProperty StrokeDashArrayProperty = DependencyProperty.Register("StrokeDashArray", typeof(DoubleCollection), typeof(TreeViewLine), new PropertyMetadata(null, new PropertyChangedCallback(TreeViewLine.OnStrokeDashArrayPropertyChanged)));
        public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register("Stroke", typeof(Brush), typeof(TreeViewLine), new PropertyMetadata(new SolidColorBrush(Colors.Black)));
        public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register("StrokeThickness", typeof(double), typeof(TreeViewLine), new PropertyMetadata(1.0));

        // Events
        public event EventHandler<PropertyChangedEventArgs<DoubleCollection>> StrokeDashArrayChanged;

        // Methods
        public TreeViewLine()
        {
            base.DefaultStyleKey = typeof(TreeViewLine);
            SetCustomDefaultValues();
        }

        private void C1TreeViewLine_StrokeDashArrayChanged(object sender, PropertyChangedEventArgs<DoubleCollection> e)
        {
            (sender as TreeViewLine).SetLineDashArray();
        }

        private T GetTemplateChild<T>(string childName, bool required, ref string errors) where T : class
        {
            DependencyObject templateChild = base.GetTemplateChild(childName);
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "template part", childName, templateChild, required, ref errors);
            return (templateChild as T);
        }

        private static Storyboard GetTemplateChildResource(FrameworkElement root, string resourceName, bool required, ref string errors)
        {
            return GetTemplateChildResource<Storyboard>(root, resourceName, required, ref errors);
        }

        private static T GetTemplateChildResource<T>(FrameworkElement root, string resourceName, bool required, ref string errors) where T : class
        {
            object child = root.Resources[resourceName];
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "resource", resourceName, child, required, ref errors);
            return (child as T);
        }

        private void InitializeLinePart()
        {
            this.SetLineDashArray();
        }

        public override void OnApplyTemplate()
        {
            string errors = string.Empty;
            base.OnApplyTemplate();
            this._isLoaded = true;
            this._elementLine = this.GetTemplateChild<Shape>("Line", true, ref errors);
            if (this._elementLine != null)
            {
                this.InitializeLinePart();
            }
            if (!string.IsNullOrEmpty(errors))
            {
                this._isLoaded = false;
                if ((base.Template != null) && !PlatformIndependent.IsInDesignMode(this))
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Template cannot be applied to TreeViewLine.\nDetails: {0}", new object[] { errors }));
                }
            }
        }

        private static void OnStrokeDashArrayPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TreeViewLine sender = d as TreeViewLine;
            if ((sender.StrokeDashArrayChanged != null) && sender._throwStrokeDashArrayChanged)
            {
                PropertyChangedEventArgs<DoubleCollection> args = new PropertyChangedEventArgs<DoubleCollection>
                {
                    OldValue = (DoubleCollection)e.OldValue,
                    NewValue = (DoubleCollection)e.NewValue
                };
                sender.StrokeDashArrayChanged(sender, args);
            }
        }

        private void SetCustomDefaultValues()
        {
            this.StrokeDashArrayChanged += new EventHandler<PropertyChangedEventArgs<DoubleCollection>>(this.C1TreeViewLine_StrokeDashArrayChanged);
        }

        private void SetLineDashArray()
        {
            if (this._elementLine != null)
            {
                DoubleCollection doubles = new DoubleCollection();
                if (this.StrokeDashArray != null)
                {
                    foreach (double num in this.StrokeDashArray)
                    {
                        doubles.Add(num);
                    }
                }
                this._elementLine.StrokeDashArray = doubles;
            }
        }

        // Properties
        public Brush Stroke
        {
            get { return (Brush)GetValue(StrokeProperty); }
            set { SetValue(StrokeProperty, value); }
        }

        public DoubleCollection StrokeDashArray
        {
            get { return (DoubleCollection)GetValue(StrokeDashArrayProperty); }
            set { SetValue(StrokeDashArrayProperty, value); }
        }

        public double StrokeThickness
        {
            get { return (double)GetValue(StrokeThicknessProperty); }
            set { SetValue(StrokeThicknessProperty, value); }
        }
    }
}
